package controller

import (
	"errors"
	"github.com/gin-gonic/gin"
	"shop-common/library/serializer"
	"shop-common/utils/contextArgs"
	"shop-common/utils/queryWrapper"
	"shop-sys/business"
	"shop-sys/pkg/code"
	"shop-sys/pkg/constant"
	"shop-sys/pkg/request"
)

type SysMenuController struct {
}

// @Tags 菜单管理
// @Summary 获取菜单页面的表
// @Security ApiKeyAuth
// @function: Table
// @Success 200 {object} string "{"code":1," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/table [get]
func (m *SysMenuController) Table(ctx *gin.Context) {
	sysMenuList, err := business.ServiceImpl().SysMenuService.ListMenuAndBtn()
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
	} else {
		serializer.SuccessData(ctx, code.StatusText(code.SUCCESS), sysMenuList)
	}
}

// @Tags 菜单管理
// @Summary 所有菜单列表(用于新建、修改角色时 获取菜单的信息)
// @Description: 获取用户所拥有的菜单(不包括按钮),通过登陆用户的userId获取用户所拥有的菜单和权限
// @Security ApiKeyAuth
// @function: List
// @Accept  json
// @Produce  json
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/list [get]
func (m *SysMenuController) List(ctx *gin.Context) {
	simpleSysMenu, err := business.ServiceImpl().SysMenuService.ListSimpleMenuNoButton()
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	}

	serializer.SuccessData(ctx, "", simpleSysMenu)
}

// @Tags 菜单管理
// @Summary 选择菜单，获取一级菜单
// @Description: 选择菜单，获取一级菜单
// @Security ApiKeyAuth
// @function: ListRootMenu
// @Accept  json
// @Produce  json
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/listRootMenu [get]
func (m *SysMenuController) ListRootMenu(ctx *gin.Context) {
	//查询列表数据
	menuList, err := business.ServiceImpl().SysMenuService.ListRootMenu()
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	}

	serializer.SuccessData(ctx, "", menuList)
}

// @Tags 菜单管理
// @Summary 选择子菜单
// @Description: 选择子菜单
// @Security ApiKeyAuth
// @function: ListChildrenMenu
// @Accept  json
// @Produce  json
// @Param parentId query int true "父菜单ID，一级菜单为0"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/listChildrenMenu [get]
func (m *SysMenuController) ListChildrenMenu(ctx *gin.Context) {
	parentId, err := contextArgs.GetUriIntQuery(ctx, "parentId")
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	//查询列表数据
	menuList, err := business.ServiceImpl().SysMenuService.ListChildrenMenuByParentId(parentId)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	}

	serializer.SuccessData(ctx, "", menuList)
}

// @Tags 菜单管理
// @Summary 菜单信息
// @Description: 菜单信息
// @Security ApiKeyAuth
// @function: Info
// @Accept  json
// @Produce  json
// @Param menuId query int true "菜单id"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/info/{menuId} [get]
func (m *SysMenuController) Info(ctx *gin.Context) {
	menuId, err := contextArgs.GetUriIntPath(ctx, "menuId")
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	info, err := business.ServiceImpl().SysMenuService.FinById(menuId)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicQueryErr)
		return
	}

	serializer.SuccessData(ctx, "", info)
}

// @Tags 菜单管理
// @Summary 获取用户所拥有的菜单和权限
// @Description: 通过登陆用户的userId获取用户所拥有的菜单和权限
// @Security ApiKeyAuth
// @function: Nav
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/nav [get]
func (m *SysMenuController) Nav(ctx *gin.Context) {
	userId, err := contextArgs.GetUserInternalId(ctx)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	// 获取数据menu
	menuList, err := business.ServiceImpl().SysMenuService.ListMenuByUserId(userId)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.ERROR))
		return
	}

	authorities, err := business.ServiceImpl().SysUserService.FindByIdPermsList(userId)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.ERROR))
		return
	}

	data := &map[string]interface{}{
		"menuList":    menuList,
		"authorities": authorities,
	}
	serializer.SuccessData(ctx, "", data)
}

func (m *SysMenuController) RolePerms(ctx *gin.Context) {
	perms, err := business.ServiceImpl().SysMenuService.FindByRoleIdPerms(nil)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.SaveMenuDataErr))
	} else {
		serializer.SuccessData(ctx, "", perms)
	}
}

// @Tags 菜单管理
// @Summary 保存菜单
// @Description: 类型(目录、菜单、按钮)
// @Security ApiKeyAuth
// @function: Save
// @Accept  json
// @Produce  json
// @Param data body request.SysMenuRequest true "请求参数"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu [post]
func (m *SysMenuController) Save(ctx *gin.Context) {
	form := request.SysMenuRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	//数据校验
	err := verifyForm(&form)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	// 保存菜单数据
	err = business.ServiceImpl().SysMenuService.Create(&form)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.SaveMenuDataErr))
	} else {
		serializer.Success(ctx, "")
	}
}

func verifyForm(form *request.SysMenuRequest) error {
	// 判断数据库是否存在相同数据
	switch form.Type {
	case constant.MenuType_CATALOG:
		wp := &queryWrapper.WherePair{Query: "name = ?", Args: []interface{}{form.Name}}
		wp = wp.And(&queryWrapper.WherePair{Query: "parent_id = ?", Args: []interface{}{form.ParentId}})
		if err := isExist(wp); err != nil {
			return err
		}
	case constant.MenuType_MENU:
		wp := &queryWrapper.WherePair{Query: "url = ?", Args: []interface{}{form.Url}}
		wp = wp.And(&queryWrapper.WherePair{Query: "parent_id = ?", Args: []interface{}{form.ParentId}})
		wp = wp.And(&queryWrapper.WherePair{Query: "name = ?", Args: []interface{}{form.Name}})
		if err := isExist(wp); err != nil {
			return err
		}
	case constant.MenuType_BUTTON:
		wp := &queryWrapper.WherePair{Query: "perms = ?", Args: []interface{}{form.Perms}}
		wp = wp.And(&queryWrapper.WherePair{Query: "parent_id = ?", Args: []interface{}{form.ParentId}})
		wp = wp.And(&queryWrapper.WherePair{Query: "name = ?", Args: []interface{}{form.Name}})
		if err := isExist(wp); err != nil {
			return err
		}
	}

	if form.Type == constant.MenuType_MENU {
		if form.Url == "" {
			return errors.New("菜单URL不能为空")
		}

	}

	if form.MenuId > 0 && form.MenuId == form.ParentId {
		return errors.New("自己不能是自己的上级")
	}

	//上级菜单类型
	parentType := constant.MenuType_CATALOG
	if form.ParentId != 0 {
		wp := &queryWrapper.WherePair{Query: "menu_id = ?", Args: []interface{}{form.ParentId}}
		parentMenu, err := business.ServiceImpl().SysMenuService.FindByParentId(wp)
		if err != nil {
			return errors.New("父菜单数据未查到")
		}
		parentType = parentMenu.Type
	}

	//目录、菜单
	if form.Type == constant.MenuType_CATALOG || form.Type == constant.MenuType_MENU {
		if parentType != constant.MenuType_CATALOG {
			return errors.New("上级菜单只能为目录类型")
		}
		return nil
	}

	//按钮
	if form.Type == constant.MenuType_BUTTON {
		if parentType != constant.MenuType_MENU {
			return errors.New("上级菜单只能为菜单类型")
		}
	}

	return nil
}

func isExist(wp *queryWrapper.WherePair) error {
	info, err := business.ServiceImpl().SysMenuService.FindByParentId(wp)
	if err != nil {
		return errors.New(code.StatusText(code.ERROR))
	}
	if info.MenuId > 0 {
		return errors.New("菜单数据已存在！")
	}
	return nil
}

// @Tags 菜单管理
// @Summary 保存菜单
// @Description: 类型(目录、菜单、按钮)
// @Security ApiKeyAuth
// @function: Update
// @Accept  json
// @Produce  json
// @Param data body request.SysMenuRequest true "请求参数"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu [put]
func (m *SysMenuController) Update(ctx *gin.Context) {
	form := request.SysMenuRequest{}
	if err := serializer.Verify(ctx, &form); err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	if form.MenuId == 0 {
		serializer.Fail(ctx, "菜单ID不能为空")
		return
	}

	//数据校验
	err := verifyForm(&form)
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	columns := map[string]interface{}{}
	columns["name"] = form.Name
	columns["parent_id"] = form.ParentId

	if form.Type == constant.MenuType_CATALOG {
		columns["order_num"] = form.OrderNum
		columns["icon"] = form.Icon
	} else if form.Type == constant.MenuType_MENU {
		columns["url"] = form.Url
		columns["perms"] = form.Perms
		columns["order_num"] = form.OrderNum
		columns["icon"] = form.Icon
	} else if form.Type == constant.MenuType_BUTTON {
		columns["perms"] = form.Perms
	}

	err = business.ServiceImpl().SysMenuService.UpdateById(form.MenuId, columns)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicUpdateErr)
		return
	}

	serializer.Success(ctx, "")
}

// @Tags 菜单管理
// @Summary 菜单信息
// @Description: 菜单信息
// @Security ApiKeyAuth
// @function: Delete
// @Accept  json
// @Produce  json
// @Param menuId query int true "菜单id"
// @Success 200 {object} string "{"code":0," result":{}, "message":"操作成功", "time":1618493448}"
// @Router /sys/menu/{menuId} [get]
func (m *SysMenuController) Delete(ctx *gin.Context) {
	menuId, err := contextArgs.GetUriIntPath(ctx, "menuId")
	if err != nil {
		serializer.Fail(ctx, err.Error())
		return
	}

	if menuId <= constant.SYS_MENU_MAX_ID {
		serializer.Fail(ctx, "系统菜单，不能删除")
		return
	}

	//判断是否有子菜单或按钮
	menuList, err := business.ServiceImpl().SysMenuService.ListChildrenMenuByParentId(menuId)
	if err != nil {
		serializer.Fail(ctx, code.StatusText(code.ERROR))
		return
	}

	if len(menuList) > 0 {
		serializer.Fail(ctx, "请先删除子菜单或按钮")
		return
	}

	err = business.ServiceImpl().SysMenuService.DeleteMenuAndRoleMenu(menuId)
	if err != nil {
		serializer.Fail(ctx, serializer.PublicDeleteErr)
		return
	}

	serializer.Success(ctx, "")
}
